package com.snoob.springboot.util.rsa;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import com.snoob.springboot.base.BaseException;
import org.apache.commons.codec.binary.Base64;

import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;

/**
 * @描述 RSA工具类
 * @作者 lixing_java@163.com
 * @日期 2023/2/7
 */
public class RsaUtil {
    // 鲸汇仓库系统默认RSA私钥
    public static final String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKQ+ffkMprMtlZyaPd9ybRsXX7dyWPzZIgEg6BUzZhpc2bg4liUzrbbCEzRzkdgQggTZBuuECnuSSyC+hO/3Fs85TMOfobsMUT0CTyYOHmpKuao7CHV8v2J9K2BTXWb2J6n2UKYxFvKMuEJbEmqBBDkwByo7iOMdu5KtFy7QW/e7AgMBAAECgYEAkBzFK+GN42n7/IzZ/VXJphu8QJp0umdLDvJwsSmITVlrL9l25O2TXuirMTq2nX7elqJXEA+rowGaKgEBZAzKVWDaubdkVs3WTWgWaQalJ6t5JLCx6PwS9hsGkwgroS5EIuCSsro590Un2iPZKWT/yiP2EwCgP4Bx82xJ6WApZQECQQDZdmDEvGNvSOSsx8KjavyF7gnmhBs5UKI6p/QEvtd2q7AS0av34+4l0zDEvYyIfX7INR4CS7B7IIlv7Gti59SHAkEAwVnCFHVORcn4Cd2kiLJeKqaDy17FeShv/iXDtjGJircFQ7Pi8em3DN08jtZyR4zt0Rjj8uu11mIbMlobI0qELQJAXWIPVgyMKqrDwEqcE68Kt7yrtbi/NBKjR8r959fIEObTWpF9ZpsTllylkabQJYC2o+TjeRrls0oamtyMlNF3GwJBAJ2VsE7IROEweU5hLQaUiZctW+FW/o9+27hBwz8tJLK/9DR32pHcMGr1rbOlKEMUo4d2R+LnJa7zCsOBGPksdIkCQQCuyw9LtjV4OykAL7AlQXjSUDjP/4vIHdRVwtHhnuHiLGifT+cGzPwmHI7XNGLOSbT5yGKnNO5bBansatUnnWm+";

    // 鲸汇仓库系统默认RSA私钥
    public static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkPn35DKazLZWcmj3fcm0bF1+3clj82SIBIOgVM2YaXNm4OJYlM622whM0c5HYEIIE2QbrhAp7kksgvoTv9xbPOUzDn6G7DFE9Ak8mDh5qSrmqOwh1fL9ifStgU11m9iep9lCmMRbyjLhCWxJqgQQ5MAcqO4jjHbuSrRcu0Fv3uwIDAQAB";

    /**
     * 初始化RSA密钥对
     */
    public static Rsa initRsaKey() {
        //生成RSA秘钥对
        KeyPair pair = SecureUtil.generateKeyPair("RSA");
        //私
        PrivateKey aPrivate = pair.getPrivate();
        String privateKey = Base64.encodeBase64String(aPrivate.getEncoded());
        //公
        PublicKey aPublic = pair.getPublic();
        String publicKey = Base64.encodeBase64String(aPublic.getEncoded());

        return new Rsa(privateKey, publicKey);
    }

    /**
     * 通过私钥对目标内容进行签名
     * @param content 目标内容
     * @param privateKey 私钥
     * @return 签名
     */
    public static String rsaSign(String content, String privateKey) throws RuntimeException {
        try {
            PrivateKey aPrivate = SecureUtil.generatePrivateKey(SignAlgorithm.SHA256withRSA.getValue(), Base64.decodeBase64(privateKey));
            Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA);
            sign.setPrivateKey(aPrivate);
            //待签名数据转换
            byte[] dataBytes = StrUtil.bytes(content, CharsetUtil.CHARSET_UTF_8);
            byte[] signBytes = sign.sign(dataBytes);
            return Base64.encodeBase64String(signBytes);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * 通过公钥对目标内容、签名进行验签
     * @param content 目标内容
     * @param signString 通过私钥对目标内容进行签名
     * @param publicKey 公钥
     * @return true or false
     */
    public static boolean rsaVerify(String content, String signString, String publicKey) {
        try {
            PublicKey aPublic = SecureUtil.generatePublicKey(SignAlgorithm.SHA256withRSA.getValue(), Base64.decodeBase64(publicKey));
            Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA);
            //签名工具
            sign.setPublicKey(aPublic);
            byte[] dataBytes = StrUtil.bytes(content, CharsetUtil.CHARSET_UTF_8);
            return sign.verify(dataBytes, Base64.decodeBase64(signString.getBytes(StandardCharsets.UTF_8)));
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    public static void main(String[] args) {
        // 初始化RSA密钥对
        //System.out.println(JSONObject.toJSONString(initRsaKey()));

//        String content = "appId=appId&uniqueNo=uniqueNo&timezoneOffset=timezoneOffset&timestamp=timestamp";
//        System.out.println("目标内容:" + content);
//
//        String sign = rsaSign(content, privateKey); // 私钥签名
//        System.out.println("签名:" + sign);
//
//        boolean flag = rsaVerify(content, sign, publicKey); // 公钥验签
//        System.out.println("验签:" + flag);


    }

}
